home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-wos-src / pasm / output_abs.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  6KB  |  168 lines

  1. /* $VER: pasm output_abs.c V1.2 (21.10.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2   (21.10.98) phx
  16.  *        Replaced obsolete R_PPC_TOC16 by real R_PPC_SDAREL16.
  17.  * v1.1d  (27.09.97) phx
  18.  *        fopen() uses binary mode "b" for windoze/msdog compatibility.
  19.  * v0.4   (05.07.97) phx
  20.  *        Absolute output format supports correct relocations and
  21.  *        aligments. The user will be warned, if external references
  22.  *        are present.
  23.  * v0.2   (25.03.97) phx
  24.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  25.  *        or ELF output format may be selected. ELF is default for all
  26.  *        currently supported platforms. PPCasm supports nine different
  27.  *        relocation types (there are much more...).
  28.  *        Compiles and works also under NetBSD/amiga (68k).
  29.  *        Changed function declaration to 'new style' in all sources
  30.  *        (to avoid problems with '...' for example).
  31.  * v0.1   (11.03.97) phx
  32.  *        First test version with all PowerPC instructions and most
  33.  *        important directives. Only raw, absolute output.
  34.  * v0.0   (04.03.97) phx
  35.  *        File created.
  36.  */
  37.  
  38.  
  39. #define OUTPUT_ABS_C
  40. #include "ppcasm.h"
  41. #define BASEREG_OFFSET 0x7ffc  /* @@@ ? */
  42.  
  43.  
  44. void output_absolute(struct GlobalVars *);
  45. static void wr_err(struct GlobalVars *);
  46.  
  47.  
  48.  
  49. void output_absolute(struct GlobalVars *gv)
  50. {
  51.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  52.   struct Reloc *nextrel,*rel;
  53.   struct XReference *xref;
  54.   unsigned long offs = gv->absbase;
  55.   FILE *fp;
  56.  
  57.   /* calculate section base addresses */
  58.   while (nextsec = (struct Section *)sec->n.next) {
  59.     if (!(sec->flags & SF_DISCARD)) {
  60.       sec->index = (uint32)offs;
  61.       offs += (sec->size + 3) & ~3;
  62.     }
  63.     sec = nextsec;
  64.   }
  65.  
  66.   /* create output file */
  67.   sec = (struct Section *)gv->sectionlist.first;
  68.   if (fp = fopen(gv->dest_name,"wb")) {
  69.     while (nextsec = (struct Section *)sec->n.next) {
  70.       if (!(sec->flags & SF_DISCARD) && sec->size) {
  71.  
  72.         /* try to resolve relocations */
  73.         rel = (struct Reloc *)sec->reloclist.first;
  74.         while (nextrel = (struct Reloc *)rel->n.next) {
  75.           uint32 *p = (uint32 *)((char *)sec->contents + rel->offset);
  76.           uint32 a = rel->relocsect->index + rel->addend;
  77.  
  78.           switch (rel->type) {
  79.             case R_PPC_ADDR32:
  80.               *p = ECVW(a);
  81.               break;
  82.             case R_PPC_ADDR16:
  83.               *(uint16 *)p = ECVH((uint16)a);
  84.               break;
  85.             case R_PPC_ADDR16_LO:
  86.               *(uint16 *)p = ECVH((uint16)(a & 0xffff));
  87.               break;
  88.             case R_PPC_ADDR16_HA:
  89.               if (a & 0x8000)
  90.                 a += 0x10000;
  91.             case R_PPC_ADDR16_HI:
  92.               *(uint16 *)p = ECVH((uint16)(a >> 16));
  93.               break;
  94.             case R_PPC_ADDR24:
  95.               *p = ECVW((uint32)((*(uint8 *)p & 0xfc) << 24) |
  96.                         (a & 0x3fffffc) | (uint32)(*((uint8 *)p+3) & 3));
  97.               break;
  98.             case R_PPC_ADDR14:
  99.             case R_PPC_ADDR14_BRTAKEN:
  100.             case R_PPC_ADDR14_BRNTAKEN:
  101.               *((uint16 *)p+1) = ECVH((uint16)(a & 0xfffc) |
  102.                                       (uint16)(*((uint8 *)p+3) & 3));
  103.               break;
  104.             case R_PPC_REL24:
  105.               *p = ECVW((uint32)((*(uint8 *)p & 0xfc) << 24) |
  106.                         ((a - (sec->index + rel->offset)) & 0x3fffffc) |
  107.                         (uint32)(*((uint8 *)p+3) & 3));
  108.               break;
  109.             case R_PPC_REL14:
  110.             case R_PPC_REL14_BRTAKEN:
  111.             case R_PPC_REL14_BRNTAKEN:
  112.               *((uint16 *)p+1) = ECVH((uint16)((a - (sec->index + 
  113.                                       rel->offset - 2)) & 0xfffc) |
  114.                                       (uint16)(*((uint8 *)p+3) & 3));
  115.               break;
  116.             case R_PPC_REL32:
  117.               *p = ECVW(a - (sec->index + rel->offset));
  118.               break;
  119.             case R_PPC_SDAREL16:
  120.               if (gv->tocsect)
  121.                 a -= gv->tocsect->index + BASEREG_OFFSET;
  122.               else
  123.                 a -= BASEREG_OFFSET;
  124.               *(uint16 *)p = ECVH((uint16)a);
  125.               break;
  126.             default:
  127.               error(53,elfrel_name[rel->type & ELFRELNAMMSK],rel->offset,
  128.                     sec->name);  /* relocation not supported */
  129.               break;
  130.           }
  131.           rel = nextrel;
  132.         }
  133.  
  134.         /* any external references? (would be difficult here :) */
  135.         while (xref = (struct XReference *)remhead(&sec->xreflist))
  136.           error(55,xref->xsymbol->name);  /* no xrefs in absolute output */
  137.  
  138.         /* write section contents */
  139.         if (sec->flags & SF_UNINITIALIZED) {  /* bss section */
  140.           unsigned long s = (sec->size + 3) >> 2;
  141.           while (s--) {
  142.             if (!fwrite(gv->alignment_bytes,1,4,fp))
  143.               wr_err(gv);
  144.           }
  145.         }
  146.         else {
  147.           if (!fwrite(sec->contents,1,sec->size,fp))
  148.               wr_err(gv);
  149.           if ((4-(sec->size&3))&3) {  /* aligment */
  150.             if (!fwrite(gv->alignment_bytes,1,(4-(sec->size&3))&3,fp))
  151.                 wr_err(gv);
  152.           }
  153.         }
  154.       }
  155.       sec = nextsec;
  156.     }
  157.     fclose(fp);
  158.   }
  159.   else
  160.     error(25,gv->dest_name);  /* unable to create output file */
  161. }
  162.  
  163.  
  164. static void wr_err(struct GlobalVars *gv)
  165. {
  166.   error(26,gv->dest_name);  /* write error */
  167. }
  168.